{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quick intro to Kernel Memory: install, upload a doc, ask a question\n",
    "\n",
    "This notebook shows the basic usage of Kernel Memory, via the serverless client.\n",
    "\n",
    "First of all, install the Kernel Memory dependency."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>Microsoft.KernelMemory.Core, 0.29.240219.2</span></li></ul></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#r \"nuget: Microsoft.KernelMemory.Core, 0.29.240219.2\"\n",
    "\n",
    "using Microsoft.KernelMemory;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For our demo, we use also the \"dotenv\" nuget, to load our secret credentials from a `.env` file.\n",
    "Make sure you create your `.env` file, with this content:\n",
    "\n",
    "> ```\n",
    "> OPENAI_API_KEY=<your OpenAI API key>\n",
    "> ```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>dotenv.net, 3.1.3</span></li></ul></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#r \"nuget: dotenv.net, 3.1.3\"\n",
    "\n",
    "dotenv.net.DotEnv.Load();\n",
    "var env = dotenv.net.DotEnv.Read();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's create an instance of Kernel Memory client using the `KernelMemoryBuilder` to configure our solution. \n",
    "\n",
    "In this demo we use OpenAI to calculate embeddings and generate text, and the default storage settings, with content and embeddings kept in a volatile memory automatically deleted after the execution."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "info: Microsoft.KernelMemory.Handlers.TextExtractionHandler[0]\n",
      "      Handler 'extract' ready\n",
      "info: Microsoft.KernelMemory.Handlers.TextPartitioningHandler[0]\n",
      "      Handler 'partition' ready\n",
      "info: Microsoft.KernelMemory.Handlers.SummarizationHandler[0]\n",
      "      Handler 'summarize' ready\n",
      "info: Microsoft.KernelMemory.Handlers.GenerateEmbeddingsHandler[0]\n",
      "      Handler 'gen_embeddings' ready, 1 embedding generators\n",
      "info: Microsoft.KernelMemory.Handlers.SaveRecordsHandler[0]\n",
      "      Handler save_records ready, 1 vector storages\n",
      "info: Microsoft.KernelMemory.Handlers.DeleteDocumentHandler[0]\n",
      "      Handler 'private_delete_document' ready\n",
      "info: Microsoft.KernelMemory.Handlers.DeleteIndexHandler[0]\n",
      "      Handler 'private_delete_index' ready\n",
      "info: Microsoft.KernelMemory.Handlers.DeleteGeneratedFilesHandler[0]\n",
      "      Handler 'delete_generated_files' ready\n"
     ]
    }
   ],
   "source": [
    "var memory = new KernelMemoryBuilder()\n",
    "    .WithOpenAIDefaults(env[\"OPENAI_API_KEY\"])\n",
    "    .Build<MemoryServerless>();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "At this point we have the memory client ready, we can import data and ask questions!\n",
    "\n",
    "Let's import a PDF file with some details about Kernel Memory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "await memory.ImportDocumentAsync(\"sample-KM-Readme.pdf\", documentId: \"doc001\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's ask a question about Kernel Memory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: What's Kernel Memory?\n",
      "\n",
      "Answer: Kernel Memory is a multi-modal AI service that specializes in efficient indexing of datasets through custom continuous data hybrid pipelines. It supports features such as Retrieval Augmented Generation (RAG), synthetic memory, prompt engineering, and custom semantic memory processing. It includes a GPT Plugin, web clients, a .NET library for embedded applications, and can be deployed as a Docker container. Kernel Memory enables natural language querying for obtaining answers from indexed data, complete with citations and links to the original sources. It is designed for seamless integration with popular AI platforms and offers support for various data formats and backends. It also provides features like security filters, long-running ingestion, custom tokenization, document storage, OCR via Azure Document Intelligence, and more. Kernel Memory can be used as a service from any language, tool, or platform, including browser extensions, chatbots, and assistants.\n"
     ]
    }
   ],
   "source": [
    "var question = \"What's Kernel Memory?\";\n",
    "\n",
    "var answer = await memory.AskAsync(question);\n",
    "\n",
    "Console.WriteLine($\"Question: {question}\\n\\nAnswer: {answer.Result}\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And here show the sources used to generate the answer above, what we call \"citations\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sources:\n",
      "\n",
      "  - sample-KM-Readme.pdf  - default/doc001/3e0c889e762b413594085c715593bbc7 [Tuesday, February 27, 2024]\n"
     ]
    }
   ],
   "source": [
    "Console.WriteLine(\"Sources:\\n\");\n",
    "\n",
    "foreach (var x in answer.RelevantSources)\n",
    "{\n",
    "    Console.WriteLine($\"  - {x.SourceName}  - {x.Link} [{x.Partitions.First().LastUpdate:D}]\");\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "languageName": "csharp",
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
